package cate.game.doc;

import cate.common.table.XSSFRowWrap;
import cate.common.table.d.GDObj;
import easy.java.codec.JsonCodec;
import easy.java.io.file.FileWrite;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@Slf4j
public class ItemConfigDocMaker {

    private static final ItemTypeParam[] ALL_TYPES = new ItemTypeParam[]{
            new ItemTypeParam("物品.xlsm", "数值资源", 0, "数值资源").setIconTitle("icon"),
            new ItemTypeParam("英雄.xlsx", "基础", 1, "英雄").setNameTitle("英雄名"),
            new ItemTypeParam("装备.xlsx", "装备", 2, "装备"),
            new ItemTypeParam("物品.xlsm", "基础物品", 3, "道具"),
            new ItemTypeParam("物品.xlsm", "碎片", 4, "碎片"),
            new ItemTypeParam("徽章.xlsx", "徽章基础", 5, "徽章").setIdTitle("徽章类型ID"),
            new ItemTypeParam("香料.xlsx", "香料基础", 6, "香料").setIdTitle("ID"),
            new ItemTypeParam("灵器.xlsx", "灵器基础", 7, "灵器").setIdTitle("灵器ID"),
            new ItemTypeParam("灵器.xlsx", "灵器碎片", 8, "灵器碎片"),
            new ItemTypeParam("家具.xlsx", "家具基础", 13, "家具").setIdTitle("家具ID").setNameTitle("家具名称").setIconTitle("家具图标"),
            new ItemTypeParam("宝物.xlsx", "宝物基础", 14, "宝物").setIdTitle("宝物ID"),
            new ItemTypeParam("新主角表.xlsx", "载具基础", 16, "载具").setIdTitle("载具ID").setNameTitle("载具名称").setQualityTitle("载具品质"),
            new ItemTypeParam("宝石.xlsx", "宝石基础表", 19, "宝石").setIdTitle("宝石ID").setNameTitle("宝石名称"),
    };
    private static final Map<String, String> LANG = new HashMap<>();
    private static String EXCEL_PATH = "E:\\project_cate\\repository\\放置美食\\策划\\上传文件\\excel\\国内主版本\\";

    public static void main(String[] args) {
        List<ItemTypeConfigDoc> all = loadAll(null);
        try {
            byte[] jsonBytes = JsonCodec.instance().encodeBytes(all);
            FileWrite.i.writeBytes(".tmp/item.config.json", jsonBytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static List<ItemTypeConfigDoc> loadAll(String excelPath) {
        if (excelPath != null) {
            EXCEL_PATH = excelPath;
        }
        loadLang();

        List<ItemTypeConfigDoc> all = new LinkedList<>();
        for (ItemTypeParam param : ALL_TYPES) {
            ItemTypeConfigDoc doc = parseTypeDoc(param);
            if (doc == null) {
                System.out.println(param.fileName + "-" + param.sheetName + " 读取配置错误");
                continue;
            }
            all.add(doc);
        }

        unloadLang();
        return all;
    }

    public static void loadLang() {
        log.info("加载lang_cn 开始");
        File excelFile = new File(EXCEL_PATH + "lang_cn.xlsx");
        if (!excelFile.exists()) {
            return;
        }
        try {
            FileInputStream fis = new FileInputStream(excelFile);
            XSSFWorkbook workbook = new XSSFWorkbook(fis);
            XSSFSheet sheet = workbook.getSheet("文本");
            if (sheet == null) {
                return;
            }

            XSSFRow headerRow = sheet.getRow(0);
            final int beg = headerRow.getFirstCellNum();
            final int end = headerRow.getLastCellNum();
            Map<String, Integer> fieldIndexMap = new HashMap<>();
            for (int i = beg; i < end; i++) {
                XSSFCell cell = headerRow.getCell(i);
                if (cell == null) {
                    continue;
                }
                String cellVal = cell.getStringCellValue().replace("*", "");
                fieldIndexMap.put(cellVal, i);
            }

            for (int i = sheet.getFirstRowNum() + 1; i < sheet.getLastRowNum(); i++) {
                XSSFRow row = sheet.getRow(i);
                if (row == null) {
                    continue;
                }

                if (i == sheet.getFirstRowNum() + 1) {
                    try {
                        XSSFCell cell = row.getCell(0);
                        if (cell != null && cell.getCellType() == CellType.STRING) {
                            String testMark = cell.getStringCellValue();
                            if (StringUtils.isNotBlank(testMark) && StringUtils.startsWith(testMark, "#")) {
                                continue;
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                XSSFRowWrap xrw = new XSSFRowWrap(row, fieldIndexMap);
                String id = xrw.getString("id");
                String text = xrw.getString("文本");
                if (id != null && text != null) {
                    LANG.put(id, text);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("加载lang_cn 结束");
    }

    public static void unloadLang() {
        LANG.clear();
    }

    public static ItemTypeConfigDoc parseTypeDoc(ItemTypeParam param) {
        File excelFile = new File(EXCEL_PATH + param.fileName);
        if (!excelFile.exists()) {
            excelFile = new File(EXCEL_PATH + "$" + param.fileName);
            if (!excelFile.exists()) {
                return null;
            }
        }
        try (FileInputStream fis = new FileInputStream(excelFile)) {
            XSSFWorkbook workbook = new XSSFWorkbook(fis);
            XSSFSheet sheet = workbook.getSheet(param.sheetName);
            if (sheet == null) {
                sheet = workbook.getSheet("$" + param.sheetName);
                if (sheet == null) {
                    return null;
                }
            }
            return parseTypeDocFromSheet(param, sheet);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static ItemTypeConfigDoc parseTypeDocFromSheet(ItemTypeParam param, XSSFSheet sheet) {
        ItemTypeConfigDoc doc = new ItemTypeConfigDoc();
        doc.type = param.type;
        doc.name = param.typeName;
        doc.items = new LinkedList<>();

        XSSFRow headerRow = sheet.getRow(0);
        final int beg = headerRow.getFirstCellNum();
        final int end = headerRow.getLastCellNum();
        Map<String, Integer> fieldIndexMap = new HashMap<>();
        for (int i = beg; i < end; i++) {
            XSSFCell cell = headerRow.getCell(i);
            if (cell == null) {
                continue;
            }
            String cellVal = cell.getStringCellValue().replace("*", "");
            fieldIndexMap.put(cellVal, i);
        }

        for (int i = sheet.getFirstRowNum() + 1; i <= sheet.getLastRowNum(); i++) {
            XSSFRow row = sheet.getRow(i);
            if (row == null) {
                continue;
            }

            if (i == sheet.getFirstRowNum() + 1) {
                try {
                    XSSFCell cell = row.getCell(0);
                    if (cell != null && cell.getCellType() == CellType.STRING) {
                        String testMark = cell.getStringCellValue();
                        if (StringUtils.isNotBlank(testMark) && StringUtils.startsWith(testMark, "#")) {
                            continue;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

            XSSFRowWrap xrw = new XSSFRowWrap(row, fieldIndexMap);
            Integer id = xrw.getInteger(param.idTitle);
            String name = xrw.getString(param.nameTitle);
            String limit = xrw.getString("是否禁发");
            if (id == null || name == null) {
                continue;
            }
            int quality = xrw.getInteger(param.qualityTitle, 0);
            String icon = xrw.getString(param.iconTitle);
            ItemConfigDoc itemDoc = new ItemConfigDoc();
            itemDoc.id = id;
            itemDoc.type = param.type;
            itemDoc.name = LANG.getOrDefault(name, name);
            itemDoc.quality = quality;
            itemDoc.icon = icon;
            if (limit == null || limit.isEmpty()) {
                itemDoc.disabled = false;
                itemDoc.warn = 0;
            } else {
                if (limit.equals("0")) {
                    itemDoc.disabled = false;
                    itemDoc.warn = 0;
                } else if (limit.equals("1")) {
                    itemDoc.disabled = true;
                    itemDoc.warn = 0;
                } else {
                    String[] splits = limit.split("#");
                    if (splits.length != 2 || !splits[0].equals("0")) {
                        System.out.println(param.fileName + "-" + row.getSheet().getSheetName() + "-" + itemDoc.id + " 禁发配置错误");
                        itemDoc.disabled = false;
                        itemDoc.warn = 0;
                    } else {
                        itemDoc.disabled = false;
                        try {
                            itemDoc.warn = Integer.parseInt(splits[1]);
                        } catch (Exception e) {
                            System.out.println(param.fileName + "-" + row.getSheet().getSheetName() + "-" + itemDoc.id + " 禁发配置错误");
                            itemDoc.warn = 0;
                        }
                    }
                }
            }
            if (param.type == GDObj.Type.HERO) {
                itemDoc.heroExtra = new HeroConfigExtra();
                itemDoc.heroExtra.protoId = xrw.getInteger("原型id", 0);
                itemDoc.heroExtra.star = xrw.getInteger("星级", 0);
                itemDoc.heroExtra.camp = xrw.getInteger("阵营", 0);
            } else if (param.type == GDObj.Type.EQUIP) {
                itemDoc.equipExtra = new EquipConfigExtra();
                itemDoc.equipExtra.elite = xrw.getByte("精英装备", (byte) 0);
            } else if (param.type == GDObj.Type.HERO_PART) {
                itemDoc.heroPartExtra = new HeroPartConfigExtra();
                itemDoc.heroPartExtra.type = xrw.getByte("类型", (byte) 0);
                itemDoc.heroPartExtra.camp = xrw.getInteger("阵营", 0);
                itemDoc.heroPartExtra.protoId = xrw.getInteger("伙伴id", 0);
                if (itemDoc.heroPartExtra.protoId > 0) {
                    itemDoc.heroPartExtra.protoId++;
                }
            } else if (param.type == GDObj.Type.RUNE) {
                itemDoc.runeExtra = new RuneConfigExtra();
                itemDoc.runeExtra.level = xrw.getInteger("徽章等级", 0);
            } else if (param.type == GDObj.Type.FAIRY) {
                itemDoc.fairyExtra = new FairyConfigExtra();
                itemDoc.fairyExtra.type = xrw.getByte("灵器类型", (byte) 0);
                itemDoc.fairyExtra.level = xrw.getInteger("等级", 0);
                itemDoc.fairyExtra.protoId = xrw.getInteger("专属英雄", 0);
                if (itemDoc.fairyExtra.protoId > 0) {
                    itemDoc.fairyExtra.protoId++;
                }
            }  else if (param.type == GDObj.Type.GEM) {
                itemDoc.gemExtra = new GemConfigExtra();
                itemDoc.gemExtra.level = xrw.getInteger("等级", 0);
            }
            doc.items.add(itemDoc);
        }
        return doc;
    }

    public static class ItemConfigDoc {
        public int id;
        public String name;
        public int type;
        public int quality;
        public String icon;
        public boolean disabled;
        public int warn;
        public HeroConfigExtra heroExtra;
        public EquipConfigExtra equipExtra;
        public HeroPartConfigExtra heroPartExtra;
        public RuneConfigExtra runeExtra;
        public FairyConfigExtra fairyExtra;
        public FairyPartConfigExtra fairyPartExtra;
        public GemConfigExtra gemExtra;
    }

    public static class HeroConfigExtra {
        public int protoId;
        public int star;
        public int camp;
    }

    public static class EquipConfigExtra {
        public byte elite;
    }

    public static class HeroPartConfigExtra {
        public byte type;
        public int camp;
        public int protoId;
    }

    public static class RuneConfigExtra {
        public int level;
    }

    public static class FairyConfigExtra {
        public byte type;
        public int level;
        public int protoId;
    }

    public static class FairyPartConfigExtra {
        public byte type;
        public int protoId;
        public int fairyId;
    }

    public static class VehicleConfigExtra {
        public int level;
    }

    public static class TreasureConfigExtra {
        public int level;
    }

    public static class GemConfigExtra {
        public int level;
    }

    public static class ItemTypeConfigDoc {
        public int type;
        public String name;
        public List<ItemConfigDoc> items;
    }

    static class ItemTypeParam {
        public String fileName;
        public String sheetName;
        public int type;
        public String typeName;
        public String idTitle = "id";
        public String nameTitle = "名称";
        public String qualityTitle = "品质";
        public String iconTitle = "图标";

        public ItemTypeParam(String fileName, String sheetName, int type, String typeName) {
            this.fileName = fileName;
            this.sheetName = sheetName;
            this.type = type;
            this.typeName = typeName;
        }

        public ItemTypeParam setIdTitle(String idTitle) {
            this.idTitle = idTitle;
            return this;
        }

        public ItemTypeParam setNameTitle(String nameTitle) {
            this.nameTitle = nameTitle;
            return this;
        }

        public ItemTypeParam setQualityTitle(String qualityTitle) {
            this.qualityTitle = qualityTitle;
            return this;
        }

        public ItemTypeParam setIconTitle(String iconTitle) {
            this.iconTitle = iconTitle;
            return this;
        }
    }
}
